package com.zq.server.api.service.impl;

import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.TimeUnit;

import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import com.zq.common.constant.*;
import com.zq.common.core.context.BaseContext;
import com.zq.common.core.domain.Result;
import com.zq.common.core.domain.entity.UserInfo;
import com.zq.common.core.redis.RedisCache;
import com.zq.common.enums.BusinessEnum;
import com.zq.common.enums.NotifyTypeEnum;
import com.zq.common.exception.base.BaseException;
import com.zq.common.utils.SecurityUtils;
import com.zq.common.utils.StringUtils;
import com.zq.server.admin.dao.SysActivityNotifyMapper;
import com.zq.server.admin.domain.SysActivityNotify;
import com.zq.server.admin.domain.SysNotify;
import com.zq.server.admin.service.ISysActivityNotifyService;
import com.zq.server.admin.service.ISysNotifyService;
import com.zq.server.api.dao.*;
import com.zq.server.api.domain.dto.OrdersPaymentDTO;
import com.zq.server.api.domain.dto.OrdersSubmitDTO;
import com.zq.server.api.domain.entity.*;
import com.zq.server.api.domain.vo.OrderSubmitVO;
import com.zq.server.api.domain.vo.TicketCheckVo;
import com.zq.server.api.service.ApiOrdersService;
import com.zq.server.core.sevcice.WebSocketServer;
import com.zq.server.core.sevcice.weChatTokenService;

import io.lettuce.core.RedisException;
import lombok.extern.slf4j.Slf4j;
/**
 * @author Super
 * @description 针对表【orders(订单表)】的数据库操作Service实现
 * @createDate 2024-02-26 22:35:33
 */
@Service
@Slf4j
public class ApiOrdersServiceImpl implements ApiOrdersService {

    @Autowired
    private OrdersMapper ordersMapper;
    @Autowired
    private OrderDetailMapper orderDetailMapper;
    @Autowired
    private GroupMapper groupMapper;
    @Autowired
    private UserInfoMapper userInfoMapper;

    @Autowired
    private GroupMemberMapper groupMemberMapper;
    @Autowired
    private RedisCache redisCache;

    @Autowired
    private WebSocketServer webSocketServer;

    @Autowired
    private weChatTokenService weChatTokenServices;

    @Autowired
    private ISysActivityNotifyService sysActivityNotifyService;

    @Autowired
    private SysActivityNotifyMapper notifyMapper;

    @Autowired
    private ISysNotifyService notifyService;

    /**
     * 用户下单
     *
     * @param ordersSubmitDTO
     * @return OrderSubmitVO
     */
    @Transactional
    public OrderSubmitVO submitOrder(OrdersSubmitDTO ordersSubmitDTO) {

        UserInfo user = SecurityUtils.getWeChatUser().getUser();
        // 检查用户是否满足条件
        checkUserOrderConditions(user, ordersSubmitDTO);
        // 创建订单 订单明细 视图 对象
        ApiOrders orders = buildOrdersObject(ordersSubmitDTO, user);
        ordersMapper.save(orders);
        ApiOrderDetail orderDetail = buildOrderDetailObject(orders.getId(), ordersSubmitDTO);
        orderDetailMapper.save(orderDetail);
        OrderSubmitVO orderSubmitVO = buildOrderSubmitVO(orders, ordersSubmitDTO);
        // 将订单存储到缓存中 15分钟
        storeOrderInCache(orderSubmitVO);
        return orderSubmitVO;
    }

    /**
     * 检查用户是否满足下单条件
     *
     * @param user
     * @param ordersSubmitDTO
     */
    private void checkUserOrderConditions(UserInfo user, OrdersSubmitDTO ordersSubmitDTO) {
        if (user == null || user.getUPhone() == null) {
            // 如果用户信息为空或用户手机号为空，则抛出用户异常
            throw new BaseException(BusinessEnum.PHONE_NUMBER_NOT_FOUND);
        }
        // 检查组是否满员
        ApiGroup isGroupFull = groupMapper.isGroupFull(ordersSubmitDTO.getGroupId());
        if (isGroupFull != null) {
            log.error("{} {} 人数：{}", OrderConstants.GROUP_ERROR, isGroupFull.getGId(), isGroupFull.getGGroupNumber());
            // 如果组已满员，则抛出订单业务异常
            throw new BaseException(BusinessEnum.GROUP_ERROR_MAX);
        }
        // 检查用户是否已经参加活动
        int userIsJoinActivityList =
            groupMemberMapper.userIsJoinActivity(ordersSubmitDTO.getActivityId(), user.getId());
        if (userIsJoinActivityList != NumberConstants.ZERO_) {
            // 检查用户是否已经参加活动，则抛出用户异常
            throw new BaseException(BusinessEnum.ACTIVITY_IS_JOIN_ERROR);
        }
        // 检查用户在今天是否参加活动 如果有则取消下单
        boolean isUserJoinedActivityToday = ordersMapper.isUserJoinedActivityToday(user.getId());
        if (isUserJoinedActivityToday) {
            throw new BaseException(BusinessEnum.NOW_ALREADY_ACTIVITY);
        }

    }

    /**
     * 构建订单对象
     *
     * @param ordersSubmitDTO
     * @param user
     * @return
     */
    private ApiOrders buildOrdersObject(OrdersSubmitDTO ordersSubmitDTO, UserInfo user) {
        ApiOrders orders = new ApiOrders();
        BeanUtils.copyProperties(ordersSubmitDTO, orders);
        orders.setUserId(user.getId());
        orders.setOrderTime(LocalDateTime.now());
        orders.setPayStatus(ApiOrders.UN_PAID);
        orders.setStatus(OrderStatusConstants.STAY_PAY);
        orders.setNumber(String.valueOf(System.currentTimeMillis()));
        orders.setPhone(user.getUPhone());
        orders.setUserName(user.getUName());
        orders.setGroupId(ordersSubmitDTO.getGroupId());
        orders.setAmount(ordersSubmitDTO.getAmount());
        return orders;
    }

    /**
     * 构建订单明细对象
     *
     * @param orderId
     * @param ordersSubmitDTO
     * @return
     */
    private ApiOrderDetail buildOrderDetailObject(Long orderId, OrdersSubmitDTO ordersSubmitDTO) {
        ApiGroup group = groupMapper.getByGIdGroup(ordersSubmitDTO.getGroupId());
        ApiOrderDetail orderDetail = new ApiOrderDetail();
        orderDetail.setOrder_id(orderId);
        orderDetail.setName(group.getGName());
        orderDetail.setGroup_id(group.getGId());
        orderDetail.setActivity_id(ordersSubmitDTO.getActivityId());
        orderDetail.setAmount(ordersSubmitDTO.getAmount());
        orderDetail.setAddress(ordersSubmitDTO.getAAddress());
        orderDetail.setActivityTime(ordersSubmitDTO.getActivityTime());
        return orderDetail;
    }

    /**
     * 构建订单提交视图对象
     *
     * @param orders
     * @param ordersSubmitDTO
     * @return
     */
    private OrderSubmitVO buildOrderSubmitVO(ApiOrders orders, OrdersSubmitDTO ordersSubmitDTO) {
        // 构建订单提交视图对象
        return OrderSubmitVO.builder().image(ordersSubmitDTO.getImage()).orderTime(orders.getOrderTime())
            .id(orders.getId()).orderNumber(orders.getNumber()).orderAmount(orders.getAmount())
            .aTitle(ordersSubmitDTO.getATitle()).activityTime(ordersSubmitDTO.getActivityTime())
            .aAddress(ordersSubmitDTO.getAAddress()).status(orders.getStatus()).build();
    }

    /**
     * 将订单存储到缓存中
     *
     * @param orderSubmitVO
     */
    private void storeOrderInCache(OrderSubmitVO orderSubmitVO) {
        redisCache.setCacheObject(orderSubmitVO.getOrderNumber(), orderSubmitVO, NumberConstants.FIFTEEN_,
            TimeUnit.MINUTES);

        if (!redisCache.hasKey(orderSubmitVO.getOrderNumber())) {
            log.error(RedisConstant.REDIS_ERROR);
            throw new RedisException(RedisConstant.REDIS_ERROR);
        }
    }

    /**
     * 订单支付
     *
     * @param ordersPaymentDTO 订单支付DTO
     * @return 返回支付结果信息
     */
    @Transactional
    public String payment(OrdersPaymentDTO ordersPaymentDTO) {
        UserInfo user = userInfoMapper.getUserInfoByUserId(SecurityUtils.getWechatUserId());
        paySuccess(ordersPaymentDTO.getOrderNumber(), user);
        return "支付成功";
    }

    /**
     * 支付成功，修改订单状态
     *
     * @param outTradeNo 订单号
     * @param user 用户信息
     */
    @Transactional
    public void paySuccess(String outTradeNo, UserInfo user) {
        // 根据订单号查询当前用户的订单
        ApiOrders ordersDB = getOrderByNumberAndUserId(outTradeNo, user.getId());
        try {
            // 更新订单状态为待确认、支付状态为已支付、支付方式为微信支付、备注信息为无、结账时间为当前时间
            updateOrderMessage(ordersDB);
            // 用户加入组
            addMemberToGroup(ordersDB.getGroupId(), user);
            // 判断组是否满员，如果满员则进行组封锁
            checkAndLockGroup(ordersDB.getGroupId());
            // 构建webSocket
            builderActivityNotify(ordersDB.getId(), "支付成功", "您已支付成功，您可以邀请朋友一起踢组球");
        } catch (Exception e) {
            // 记录日志
            log.error("Error occurred during payment success process: {}", e.getMessage());
            // 抛出自定义异常或向上抛出异常
            throw new BaseException("支付成功处理异常");
        }

    }

    /**
     * 根据订单号和用户ID查询订单
     *
     * @param orderNumber 订单号
     * @param userId 用户ID
     * @return 订单对象
     */
    private ApiOrders getOrderByNumberAndUserId(String orderNumber, Long userId) {
        ApiOrders orders = ordersMapper.getByNumberAndUserId(orderNumber, userId);
        if (orders == null) {
            log.error("没有获取到订单{}", orderNumber);
            throw new BaseException(OrderConstants.ORDER_NOT_FOUND);
        }
        return orders;
    }

    /**
     * 更新订单状态
     *
     * @param orderId 订单ID
     * @param status 订单状态
     * @param payStatus 支付状态
     * @param payMethod 支付方式
     * @param remark 备注
     * @param checkoutTime 结账时间
     * @param cancelTime 取消时间
     */
    private void updateOrderMessage(ApiOrders order) {
        ApiOrders orders = ApiOrders.builder().id(order.getId()).checkoutTime(LocalDateTime.now())
            .status(OrderStatusConstants.OVER_PAY).payStatus(PayStatusConstant.STAY_PAY)
            .payMethod(PayMethodConstant.WX_PAY).remark(order.getRemark()).cancelTime(order.getCancelTime()).build();
        ordersMapper.update(orders);
    }

    /**
     * 用户加入组
     *
     * @param groupId 组ID
     * @param user 用户信息
     */
    private void addMemberToGroup(Long groupId, UserInfo user) {
        ApiGroupMember member = new ApiGroupMember();
        member.setGmGroupid(groupId);
        member.setGmUserId(user.getId());
        member.setGmRole("普通"); // TODO
        member.setGmParticipantName(user.getUName());
        member.setGmParticipantImage(user.getUHeadportrait());
        member.setGmJointime(LocalDateTime.now());
        groupMemberMapper.insert(member);
    }

    /**
     * 判断组是否满员，如果满员则进行组封锁
     *
     * @param groupId 组ID
     */
    private void checkAndLockGroup(Long groupId) {
        ApiGroup groupInfo = groupMapper.isGroupFull(groupId);
        if (groupInfo != null && groupInfo.getGGroupNumber() != null) {
            log.error("进行组封锁人员已满 {} 人数：{}", groupInfo.getGId(), groupInfo.getGGroupNumber());
            // 进行组封锁
            groupInfo.setGStatus(groupStatusConstants.FULL);
            groupInfo.setGUpdatetime(LocalDateTime.now());
            groupMapper.update(groupInfo);
        }
    }

    /**
     * 获取用户待支付的订单
     *
     * @return
     */
    public List<OrderSubmitVO> getUnpaidOrders() {
        // 用户id
        Long userId = BaseContext.getCurrentId();
        if (null == userId) {
            throw new BaseException(SystemConstant.SYSTEM_ERROR);
        }
        List<ApiOrders> orders = ordersMapper.getAssignStatusOrders(userId, OrderStatusConstants.STAY_PAY);
        List<OrderSubmitVO> orderSubmitVOList = getOrderSubmitVOList(orders);
        return orderSubmitVOList;
    }

    /**
     * 获取用户所有订单
     *
     * @return
     */
    public List<OrderSubmitVO> getUserOrderList() {
        // 用户id
        Long userId = BaseContext.getCurrentId();
        if (null == userId) {
            throw new BaseException(SystemConstant.SYSTEM_ERROR);
        }
        List<ApiOrders> orders = ordersMapper.getUserOrderList(userId);
        List<OrderSubmitVO> orderSubmitVOList = getOrderSubmitVOList(orders);
        return orderSubmitVOList;
    }

    /**
     * 用户验票
     *
     * @param orderNumber 订单号
     * @return 修改结果
     */

    @Override
    @Transactional
    public Result updateUserTicketState(String orderNumber) {
        // 根据订单号查询当前用户的订单
        ApiOrders ordersDB = getOrderByNumberAndUserId(orderNumber, BaseContext.getCurrentId());
        getIsOnUpdateOrderStatus(ordersDB);
        ordersDB.setStatus(NumberConstants.FOUR_);
        // TODO 修改时间为修改
        ordersMapper.update(ordersDB);
        builderActivityNotify(ordersDB.getId(), "已签到", "祝您玩的开心，耍的愉快");
        builderAdminActivityNotify(ordersDB.getId());
        builderSystemActivityNotify(ordersDB.getId());
        return Result.success();
    }

    /**
     * 获取用户所有已支付的订单
     */
    @Override
    public List<TicketCheckVo> getUserStayTicketCheck() {
        Long UserId = BaseContext.getCurrentId();
        List<TicketCheckVo> userStayTicketCheckList =
            ordersMapper.getUserStayTicketCheckList(UserId, NumberConstants.TWO_);
        if (userStayTicketCheckList.isEmpty()) {
            return null;
        }
        return userStayTicketCheckList;
    }

    /**
     * 用户根据手机尾号（四位）和订单id进行验票
     *
     * @param orderId 订单id
     * @param phone 手机尾号“ 1 2 3 4 ”
     * @return 验票是否成功
     */
    @Override
    @Transactional(rollbackFor = BaseException.class)
    public Result phoneVerificationTicket(Long orderId, String phone) {
        // 满足条件的记录数 返回 ------status
        Integer selectNumber = ordersMapper.phoneVerificationTicket(orderId, phone);
        if (StringUtils.isNull(selectNumber)) {
            return Result.error("未找到该用户,请重新输入");
        }
        // 未验票 -- 2
        if (selectNumber == NumberConstants.TWO_) {
            ApiOrders orders = new ApiOrders();
            orders.setId(orderId);
            orders.setStatus(NumberConstants.FOUR_);
            ordersMapper.update(orders);
            //
            builderActivityNotify(orderId, "已签到", "祝您玩的开心，耍的愉快");
            builderAdminActivityNotify(orderId);
            builderSystemActivityNotify(orderId);
            return Result.success("验票成功");
        }
        // 已验票 -- 4
        if (selectNumber == NumberConstants.FOUR_) {
            return Result.error("该用户验票过了");
        }

        // 系统异常
        log.error("手机号验证异常：orderId={}, phone={}", orderId, phone);
        throw new BaseException("40001", "系统异常");
    }

    /**
     * /构建webSocket
     *
     * @作者 Caige
     * @日期 2024.3.26 17:55
     * @Description
     * @param orderId
     */
    private void builderActivityNotify(Long orderId, String msgHead, String message) {
        ApiActivity activity = notifyMapper.getActivity(orderId);
        SysActivityNotify msg = SysActivityNotify.builder().sendTime(LocalDateTime.now()).targetType(1)
            .targetId(SecurityUtils.getWechatUserId()).activityId(activity.getId()).activityImage(activity.getAImages())
            .activityTitle(activity.getATitle()).msgHead(msgHead).message(message)
            .type(NotifyTypeEnum.FRONT.getNumber())
                .status(1)
                .build();
        sysActivityNotifyService.insertNotify(msg);
//        webSocketServer.sendToOne(SecurityUtils.getWechatUserId().toString(), JSONObject.toJSONString(msg));
    }

    /**
     * /构建webSocket
     *
     * @作者 Caige
     * @日期 2024.3.26 17:55
     * @Description
     * @param orderId
     */
    private void builderSystemActivityNotify(Long orderId) {
        ApiActivity activity = notifyMapper.getActivity(orderId);
        String stringBuffer = "您已成功报名" + activity.getATitle() + ", 时间：" + activity.getActivity_time() +
                ",地址" + activity.getAAddress() + ",联系电话:" +
                SecurityUtils.getWeChatUser().getUser().getUPhone() + "。";
           SysNotify msg = SysNotify.builder().sendTime(LocalDateTime.now()).targetType(1)
            .targetId(SecurityUtils.getWechatUserId()).message(stringBuffer)
            .type(NotifyTypeEnum.FRONT.getNumber())
                   .status(1)
                   .build();
        notifyService.insertNotify(msg);
//        webSocketServer.sendToOne(SecurityUtils.getWechatUserId().toString(), JSONObject.toJSONString(msg));
    }

    /**
     * /构建webSocket
     *
     * @作者 Caige
     * @日期 2024.3.26 17:55
     * @Description
     * @param orderId
     */
    private void builderAdminActivityNotify(Long orderId) {
        ApiActivity activity = notifyMapper.getActivity(orderId);
        SysActivityNotify messages = SysActivityNotify.builder().targetType(1).sendTime(LocalDateTime.now())
            .targetId(activity.getACreatoropenid()).activityId(activity.getId()).activityImage(activity.getAImages())
            .activityTitle(activity.getATitle())
            .msgHead(SecurityUtils.getWeChatUser().getUser().getUName().concat("成功上车啦 ")).message("快去看看吧")
            .type(NotifyTypeEnum.FRONT.getNumber()).build();
        sysActivityNotifyService.insertNotify(messages);
//        webSocketServer.sendToOne(activity.getACreatoropenid().toString(), JSONObject.toJSONString(messages));
    }

    /**
     * @param param
     * @return 是否可以修改
     */
    private void getIsOnUpdateOrderStatus(ApiOrders param) {
        if (param.getPayStatus() != NumberConstants.ONE_) {
            throw new BaseException("10020", "支付状态有误");
        }
        if (param.getStatus() != NumberConstants.TWO_) {
            throw new BaseException("10020", "订单状态有误");
        }
        if (param.getStatus() != NumberConstants.TWO && param.getStatus() != NumberConstants.FOUR_) {
            throw new BaseException("10020", "订单状态有误");
        }
    }

    /**
     * 获取用户订单信息
     *
     * @param orders 订单列表
     * @return 订单信息的VO列表
     */
    private List<OrderSubmitVO> getOrderSubmitVOList(List<ApiOrders> orders) {
        List<OrderSubmitVO> voList = new ArrayList<>();
        for (ApiOrders order : orders) {
            ApiOrderDetail detail = orderDetailMapper.getOrder_idOrderDetail(order.getId());
            OrderSubmitVO submitVO =
                OrderSubmitVO.builder().orderTime(order.getOrderTime()).orderNumber(order.getNumber()).id(order.getId())
                    .orderAmount(order.getAmount()).image("wu").aTitle(detail.getName()).aAddress(detail.getAddress())
                    .activityTime(detail.getActivityTime()).status(order.getStatus()).build();
            voList.add(submitVO);
        }
        return voList;
    }

}
